`timescale 1ns / 1ps
module MCP_SEND
(
    input             iClk,             //100MHz
    input             iRst_n,
    input             i_miso      ,                                                                		   
    output wire       o_sck       ,                      
    output wire       o_mosi      ,                      
    output wire       o_ssn       ,
    input             iSend_Req, //发送请求
	output reg        osend_done,        //发送成功
	input  wire[63:0] i_can_data,
	output wire [7:0]  state         
	
);
//*******************参数定义*******************
parameter SEND_ID={8'haa,8'h08,8'hbb,8'hcc};         //send can id

localparam S0  = 8'd0;
localparam S1  = 8'd1;
localparam S2  = 8'd2;
localparam S3  = 8'd3;
localparam S4  = 8'd4;
localparam S5  = 8'd5;
localparam S6  = 8'd6;
localparam S7  = 8'd7;
localparam S8  = 8'd8;
localparam S9  = 8'd9;
localparam S10 = 8'd10;
localparam S11 = 8'd11;
localparam S12 = 8'd12;
localparam S13 = 8'd13;
localparam S14 = 8'd14;
localparam S15 = 8'd15;
localparam S16 = 8'd16;
localparam S17 = 8'd17;
localparam S18 = 8'd18;
localparam S19 = 8'd19;
localparam S20 = 8'd20;
localparam S21 = 8'd21;
localparam S22 = 8'd22;
localparam S23 = 8'd23;
//*******************发送流程*******************
reg [7:0] rvState_c;
reg [7:0] rvState_n;
wire         wFrameType1;  //1:远程帧 0：数据帧
wire         wFrameType2;  //1.扩展 0.标志
reg [1:0]  rvSide1;
wire       wSpi_Done;
reg [15:0] rvCnt1;
reg  [23:0]rvCmd_write;   //命令+地址+数据(写)
reg  [15:0]rvCmd_read;   //命令+地址(读)
reg        rWrite_En;   
reg        rRead_En;   
wire [7:0]  wvData_Read;
reg  [7:0]  rvData;
reg  [7:0]  rvData_Tx0;
assign state=rvState_c;
assign wFrameType1=1'b0;
assign wFrameType2=1'b1;
//信号边沿处理
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvSide1 <= 2'd0;
    end
    else begin
        rvSide1<={rvSide1[0],iSend_Req};
    end
end
//1段状态机
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvState_c <= S0;
    end
	else if(!iSend_Req)begin
		rvState_c <= S0;
	end
    else begin
        rvState_c <= rvState_n;
    end
end
//2段状态机
always @(*) begin 
    case(rvState_c) 
        S0:rvState_n=rvSide1==2'b01 ? S1 : rvState_c;
        S1:rvState_n=!rvData[4] ? S21 :rvState_c;
        S2:rvState_n=wSpi_Done ? S3 :rvState_c;
        S3:rvState_n=wSpi_Done ? S4:rvState_c;
        S4:rvState_n=wSpi_Done ? S5 :rvState_c;
        S5:rvState_n=wSpi_Done ? S6 :rvState_c;
        S6:rvState_n=wSpi_Done ? S7 :rvState_c;
        S7:rvState_n=wSpi_Done ? S8 :rvState_c;
        S8:rvState_n=wSpi_Done ? S9 :rvState_c;
        S9:rvState_n=wSpi_Done ? S10 :rvState_c;
        S10:rvState_n=wSpi_Done ? S11 :rvState_c;
        S11:rvState_n=wSpi_Done ? S12 :rvState_c;
        S12:rvState_n=wSpi_Done ? S13 :rvState_c;
        S13:rvState_n=wSpi_Done ? S14 :rvState_c;
        S14:rvState_n=wSpi_Done ? S15 :rvState_c;
        S15:rvState_n=wSpi_Done ? S16 :rvState_c;
        S16:rvState_n=rvCnt1>=16'd1000 ? S17 :rvState_c;
        S17:rvState_n=wSpi_Done ? S18 :rvState_c;
		S18:rvState_n=rvCnt1>=16'd1000 ? S0 :rvState_c;

		S21:rvState_n=wSpi_Done ? S22 :rvState_c;
		S22:rvState_n=wSpi_Done ? S23 :rvState_c;
		S23:rvState_n=wSpi_Done ? S2 :rvState_c;
        default :
            rvState_n=S0;
    endcase
end
//3段状态机
always @(posedge iClk or negedge iRst_n) begin 
  if(!iRst_n)
   begin
    rvCmd_write <= 24'h020000;
	rvCmd_read <= 16'h0300;
	rWrite_En <= 1'b0;
	rRead_En <= 1'b0;
	osend_done      <= 0;
	rvCnt1     <= 16'd0;
    rvData     <=8'd0;
	rvData_Tx0 <=8'd0;
   end   
  else
    begin
	  case(rvState_c)
	    S0://空闲
		  begin
            osend_done <= 1'b0;
            rWrite_En <= 1'b0;  		   
		    rRead_En <= 1'b0;
			rvCnt1<=16'd0;
		  end
		S1://读发送缓冲器30h
		  begin
            rWrite_En <= 1'b0;  		   
		    rRead_En <= wSpi_Done ? 1'b1 :1'b0;
			rvCmd_read <= {8'h03,8'h30};//读发送缓冲器
            rvData<=wSpi_Done ? wvData_Read :rvData; //bit4:检查总线是否有发送错误
		   end
		S21://发送停止
		   begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h30,rvData[7:4],1'b0,rvData[2:0]};
              rvCnt1<=16'd0;
		 end
		S22://读中断
		  begin
              rWrite_En <= 1'b0;
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h02,8'h2c};
              rvData_Tx0 <= wSpi_Done ? wvData_Read : rvData_Tx0;
		  end
		S23://复位发送中断0
		  begin
			  rRead_En <= 1'b0;
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h2c,{rvData_Tx0[7:3],1'b0,rvData_Tx0[1:0]}};
		   end
		S2://写标准标识位高位
		  begin
		    rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
            rRead_En <= 1'b0;
			rvCmd_write <= {8'h02,8'h31,SEND_ID[31:24]};
		   end
		S3://写标准标识符低位
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h32,{SEND_ID[23:16]}};
		   end
		S4://写扩展标识符高位
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h33,SEND_ID[15:8]};
		   end
		S5://写扩展标识符低位
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h34,SEND_ID[7:0]};
		   end
		S6://写发送的数据长度=8
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h35,{1'b0,wFrameType1,2'b00,4'd8}};
		   end
		S7://第1个数据
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h36,i_can_data[7:0] };
		   end
		S8:
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h37,i_can_data[15:8]};
		   end
		S9:
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h38,i_can_data[23:16]};
		   end
		S10:
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h39,i_can_data[31:24]};
		   end
		S11:
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h3a,i_can_data[39:32]};
		   end
		S12:
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h3b,i_can_data[47:40]};
		   end
		S13:
		  begin
			 rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h3c,i_can_data[55:48]};
		   end
		S14://第8个数据
		  begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h3d,i_can_data[63:56]};
		   end
		S15://数据发送
		  begin
              rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h30,8'h0b};
			  osend_done <= 1'b0;
		   end
        S16://延时1ms
		  begin
                rvCnt1<=rvCnt1>=16'd1000 ? rvCnt1 : rvCnt1+1;
		  end
		S17://发送停止
		   begin
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_write <= {8'h02,8'h30,8'h03};
              rvCnt1<=16'd0;
		 end
		S18://返回
		  begin
		    osend_done <= 1'b1;
			rvCnt1<=rvCnt1>=16'd1000 ? rvCnt1 : rvCnt1+1;
		  end
		  
		default:;
	  endcase
	
	end
end
//*******************程序调用*******************
SPI 
#  
(   .T(100),		//SPI时钟周期，1MHz
	.Len_WR(24)		//写指令的位数(写入指令+写入地址+写入的数据)
)
u_SPI_Send(
    .iClk        (iClk        ),
    .iRst_n      (iRst_n      ),
    .o_sck       (o_sck       ),
    .o_mosi      (o_mosi      ),
    .i_miso      (i_miso      ),
    .o_ssn       (o_ssn       ),
    .ivCmd_write (rvCmd_write ),
    .ivCmd_read  (rvCmd_read  ),
    .ovData      (wvData_Read      ),
    .iWrite_En   (rWrite_En   ),
    .iRead_En    (rRead_En    ),
    .oSpi_INT    (wSpi_Done    )
);



endmodule
